#include "logoutput.h"

LogOutPut *LogOutPut::ins = nullptr;
QMutex LogOutPut::m_mutex;

LogOutPut *LogOutPut::getInstance()
{
    QMutexLocker locker(&m_mutex);  //必须加锁
    if( !ins ) {
        ins = new LogOutPut();
    }
    return ins;
}

void LogOutPut::install()
{
    //创建log文件夹
    QString logPath = QApplication::applicationDirPath()+"/log";
    QDir dir(logPath);
    if( !dir.exists() ) {
        dir.mkdir(logPath);
        qDebug() << QString("运行日志文件夹创建成功:%1").arg(logPath);
    }

    //打开日志输出文件夹（不存在则创建并打开
    openTheLogFile();
    //安装消息处理函数
    qInstallMessageHandler(LogOutPut::customMessagehandler);    //此句执行后，qdebug，qinfo等才会输出到文件
    qInfo() << "-------------------日志输出模块创建成功-------------------";
}

void LogOutPut::uninstall()
{
    qInstallMessageHandler(nullptr);
}

void LogOutPut::deleteLog()
{
    //获取日志文件夹地址
    QString dirName = QApplication::applicationDirPath()+"/log";
    QDir dir(dirName);
    //获取文件夹下所有文件信息列表
    QFileInfoList infoList = dir.entryInfoList(QDir::Files);
    //遍历日志文件
    foreach (QFileInfo fileInfo, infoList) {
        //将文件创建时间与过期时间做比较，如果创建时间小于过期时间，则删除（代码是一天期限，如果改月为单位可以使用addMonths）
        if( fileInfo.birthTime() <= QDateTime::currentDateTime().addDays(-1) ) {
            QFile::setPermissions(dirName+"/"+fileInfo.fileName(),QFileDevice::ReadOther|QFileDevice::WriteOther);
            if( QFile::remove(dirName+"/"+fileInfo.fileName()) ) {
                qDebug() << "过期文件删除成功!--->" << fileInfo.fileName();
            }
            else {
                qDebug() << "过期文件删除失败!--->" << fileInfo.fileName();
            }
        }
    }
}

void LogOutPut::customMessagehandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    LogOutPut::getInstance()->outPutMsg(type,context,msg);  //调用非静态成员函数处理消息
}


LogOutPut::LogOutPut(QObject *parent)
    : QObject{parent}
{}

LogOutPut::~LogOutPut()
{
    if( m_curLogFile.isOpen() ) {
        m_curLogFile.close();
    }
    qInfo() << "日志输出模块释放";
}

void LogOutPut::outPutMsg(QtMsgType msgType, const QMessageLogContext &context, const QString &msg)
{
    //判断消息类型
    QString type;
    switch (msgType) {
    case QtDebugMsg:
        type = QString("Debug");
        break;
    case QtWarningMsg:
        type = QString("Warning");
        break;
    case QtCriticalMsg:
        type = QString("Critical");
        break;
    case QtFatalMsg:
        type = QString("Fatal");
        break;
    case QtInfoMsg:
        type = QString("Info");
    }
    m_mutex.lock(); //互斥关锁
    //文件名和行数以及函数
    QString contextInfo = QString("[File:(%1),Line:(%2),Funtion(%3)]:") \
                              .arg(context.file).arg(context.line).arg(context.function);
    //获取当前时间，精确到秒
    QDateTime curDatetime = QDateTime::currentDateTime();
    QString currentDate = curDatetime.date().toString("yyyy-MM-dd");
    QString currentTime = curDatetime.time().toString("hh:mm:ss");
    if( m_curLogFile.isOpen() ) {
        bool bFileSizeLarge = (m_curLogFile.size()>=LOG_MAX_SIZE)?true:false;
        bool bNextDate = (currentDate.compare(m_curLogFileData,Qt::CaseInsensitive)==0)?false:true;
        //当系统时间过了今天的24点到达另一天，或者超过单个日志文件最大值，切换到日志输出文件
        if( bFileSizeLarge||bNextDate ) {
            m_curLogFile.close();
            //重新打开日志输出文件(不存在则创建并打开)
            openTheLogFile();
            deleteLog();
        }
    }
    //拼接信息字符串
    QString message = QString("[%1 %2] %3: %4 %5").arg(currentDate).arg(currentTime).arg(type).arg(contextInfo).arg(msg);
    //存入信息到日志文件
    saveLog(message);
    m_mutex.unlock();   //开锁
}

void LogOutPut::saveLog(QString message)
{
    if( m_curLogFile.isOpen() ) {
        QTextStream write(&m_curLogFile);
        write << message << "\r\n";
        m_curLogFile.flush();   //刷新写入缓存
    }
}

void LogOutPut::openTheLogFile()
{
    int i=1;//当文件大小超过最大值时，给新文件添加编号
    m_curLogFileData = QDateTime::currentDateTime().toString("yyyy-MM-dd");
    //以天为单位给文件命名
    QString fileName = QApplication::applicationDirPath()+"/log/"+m_curLogFileData+"_log";
    //文件名右边（后缀）
    QString fileNameRight;
    //最终要写入的文件名
    QString fileNameList = fileName+".txt";
    //绑定文件对象
    m_curLogFile.setFileName(fileNameList);
    //判断文件大小
    while( m_curLogFile.size() >= LOG_MAX_SIZE ) {
        //给新文件加入序号后缀
        fileNameRight = QString("_%1.txt").arg(i);
        //拼接最终文件名
        fileNameList = fileName+fileNameRight;
        //修改file绑定的文件名
        m_curLogFile.setFileName(fileNameList);
        i++;
    }
    //只写和拼接的方式打开文件
    bool isopen = m_curLogFile.open(QIODevice::WriteOnly|QIODevice::Append);
    if( isopen ) {

    }
}



